package com.situ.shoplook.common.model;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 功能：
 *
 * @author 千堆雪
 * @version 1.0.0
 * <p>
 * created by 千堆雪 on 2024/8/24, last modified by 千堆雪 on 2024/8/24
 */
@Getter
@Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@ToString(exclude = {"parent", "children"})
public class Category implements Serializable {
    @EqualsAndHashCode.Include
    private Integer id;//编号
    private Integer parentId;//父类别编号
    private String name;//类别名称
    private String alias;//别名
    private String icon;//图标
    private Integer seq;//排序号
    private String description;//备注

    @JsonBackReference
    private Category parent;//父类别

    @JsonManagedReference
    private List<Category> children;//子类别

    /**
     * 构建类别树
     *
     * @param categories 所有类别实体
     * @return 类别树
     */
    public static Category buildCategoryTree(List<Category> categories) {
        Map<Integer, Category> cache = new HashMap<>();
        categories.forEach(c -> cache.put(c.getId(), c));

        //所有一级节点
        List<Category> roots = new ArrayList<>();

        for (Category c : categories) {
            if (c.getParentId() == null) {//找到根节点
                roots.add(c);
            } else {
                Integer parentId = c.getParentId();//找到父节点
                Category parent = cache.get(parentId);
                if (parent == null) {
                    throw new RuntimeException("无效的父节点");
                }
                if (parent.getChildren() == null) {
                    parent.setChildren(new ArrayList<>());
                }
                parent.getChildren().add(c);
                c.setParent(parent);
            }
        }

        Category root;
        if (roots.isEmpty()) {
            throw new RuntimeException("无根节点");
        } else if (roots.size() == 1) {
            root = roots.getFirst();
        } else {
            root = createRoot();
            roots.forEach(t -> {
                t.setParent(root);
                root.getChildren().add(t);
            });
        }

        return root;
    }

    //创建一个空根节点
    private static Category createRoot() {
        Category root = new Category();
        root.setId(0);
        root.setChildren(new ArrayList<>());
        return root;
    }

    /**
     * 深度优先查询指定编号的节点
     *
     * @param cs 所有节点集合
     * @param id 编号
     * @return 指定编号节点
     */
    public static Category deepFindById(List<Category> cs, Integer id) {
        if (CollectionUtils.isEmpty(cs)) {
            return null;
        }

        for (Category c : cs) {
            if (c.getId().equals(id)) {
                return c;
            }
            if (!CollectionUtils.isEmpty(c.getChildren())) {
                Category target = deepFindById(c.getChildren(), id);
                if (target != null) {
                    return target;
                }
            }
        }
        return null;
    }

    //查询指定编号的子节点
    public Category deepFindById(Integer id) {
        if (this.getId().equals(id)) {
            return this;
        }
        return deepFindById(this.getChildren(), id);
    }
}
